package org.bminfo.sequence;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.biojava.bio.BioException;
import org.biojava.bio.seq.Sequence;
import org.biojava.bio.seq.SequenceIterator;
import org.biojava.bio.seq.db.SequenceDB;
import org.biojava.bio.seq.io.SeqIOTools;
import org.biojava.bio.symbol.Alphabet;
import org.biojava.bio.symbol.AlphabetManager;



public class FastaSeq {
	
	  private SequenceDB db = null;

	/**
	   * The program takes two args: the first is the file name of the Fasta file.
	   * The second is the name of the Alphabet. Acceptable names are DNA RNA or PROTEIN.
	   */	
	public FastaSeq(String infile, String seqType) {
		  try {
		      //setup file input
			 String tmpfile = this.SequenceClean(infile);
			  
		      BufferedInputStream is =
		          new BufferedInputStream(new FileInputStream(tmpfile));
		 
		 
		      //get the appropriate Alphabet
		      Alphabet alpha = AlphabetManager.alphabetForName(seqType);
		 
		      //get a SequenceDB of all sequences in the file
		      db  = SeqIOTools.readFasta(is, alpha);
		    }
		    catch (BioException ex) {
		      //not in fasta format or wrong alphabet
		      ex.printStackTrace();
		    }catch (NoSuchElementException ex) {
		      //no fasta sequences in the file
		      ex.printStackTrace();
		    }catch (FileNotFoundException ex) {
		      //problem reading file
		      ex.printStackTrace();
		    }
	}
/*
 * Sequence cleaning before feed it to BioJava
 */
	private String SequenceClean(String infile) {
		RawInput rin = new RawInput();
		String outfile = rin.GetTemporaryFilePath();
		ArrayList<String> lines = rin.GetListByEachLine(infile, false);
		rin.CreateFile(outfile);
		for(String line: lines){
			if(!line.matches("^>")){
				line = line.replaceAll(" ", "");
				
				line = line.replaceAll("-", "");
			}
			rin.WriteFile(outfile, line);
		}
		rin.CloseFile(outfile);
//		System.out.println(rin.GetFullText(outfile));
		return outfile;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String infile = "snp.txt";
		FastaSeq fasta = new FastaSeq(infile, "DNA");
//		String seq = fasta.GetFirstSequence().seqString();
//		System.out.println(fasta.GetFirstSequence().getName());
//		System.out.println(seq);
		
		HashMap<String,String> seqs = fasta.getHashSequence("(Reference|mut\\d+)$");
		for(String id: seqs.keySet()){
			System.out.println(id);
			System.out.println(seqs.get(id));
		}
	}

private HashMap<String, String> getHashSequence(String rxName) {
	HashMap<String, String> allseqs = new HashMap<String, String>();
	SequenceIterator a = db.sequenceIterator();
	while(a.hasNext()){
		try {
			Sequence seq = a.nextSequence();
			
			if(rxName.isEmpty())
				allseqs.put(seq.getName(), seq.seqString());
			else{
				Pattern pName = Pattern.compile("(" + rxName + ")", Pattern.CASE_INSENSITIVE);
				Matcher mName = pName.matcher(seq.getName());
				if(mName.find()){
					allseqs.put(mName.group(1), seq.seqString());
				}else{
					allseqs.put(seq.getName(), seq.seqString());
				}
			}
				
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BioException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	return allseqs;
}
	/*
 * Definition: Get first sequence of fasta file. In case there is
 * 			only one sequence in it. The sequence will be returned.
 */
	public  Sequence GetFirstSequence() {
		SequenceIterator a = db.sequenceIterator();
		while(a.hasNext()){
			try {
				return a.nextSequence();
			} catch (NoSuchElementException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (BioException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return null;
	}

}
